

  // R (读属性) 命令固定
  // W（写属性）的命令发送前需要调整参数值 W后&前的四个字节就是设置的值
  //##0002R0000&01d4**
  //##0002R0004&01D8**

var mcuCommandData = {
    machineSpeed :          "0000",  //发动机速度
    controllerOutCurrent :  "0001", //控制器输出电流
    machineWorkState :      "0002", //发动机工作状态
    machineErrorState :     "0003", //发动机故障状态
    machineTemperature :    "0004", //发动机温度
    controllerTemperature : "0005", //控制器温度
    oilLevel :              "0006", //邮箱油位
    timeHour :              "0007", //当前运行时间 时
    timeMin :               "0008",//当前运行时间 分
    controllerOutVoltage :  "0009", //控制器输出电压 ，瞬时电压
    controllerOutVoltageR : "000A", //控制器输出电压控制 R ，设置电压
    chargeCurrentR :        "000B", //充电电流 R
    autoStartVoltageR :     "000C",//自动启动电压 R
    autoStopCurrentR :      "000D",//自动停机电流 R
    autoStopVoltageR :      "000E", //自动停机电压 R
    stopTimeHour :         "000F", //剩余停机时间（时） R
    stopTimeMin :          "0010", //剩余停机时间（分） R
    stopTimeSecR :          "0011", //电流低或电压高停机时间（秒） R

    //***********需要一定权限 **********/
    adjust_P_R :      "0012", //比列调节 R
    adjust_I_R :      "0013", //积分调节 R
    adjust_D_R :      "0014", //微分调节 R
    adjustVoltageR :  "0015", //电压校正 R
    adjustCurrentR :  "0016", //电流校正 R
    sampleTimeR :     "0017", //采样时间 R
    //*********************************/

    appVersion :  "0018", //读取软件版本号

    switchAuto :  "001BW0000",//切换手动自动 发动机手动、自动切换
    start :       "001cWDr00", //启 APP写Dr反馈发动机状态
    stop :        "001cW00St", //停 APP写St反馈发动机状态

    update : "001DW00Up", //控制器升级 APP写Up反馈软件版本号进入升级画面

    machineVersion :  "0019" , //产品型号
    machineMode :     "001A" , //模式控制
    startTimeHour :   "001E" , //启动时间 时
    startTimeMin :    "001F" , //启动时间 分
    plusContral :     "0020" , //加浓控制
    adjust :          "0021" , //稳定性调节
    sleepTimeHour:    "0022" , //休眠时
    sleepTimeMin:     "0023" , //休眠分
    timerContralBit:  "0024" , //时间启动停止位 写：0x0101启用定时停0x0100停用定时停0x0202:启用定时启0x0200:停用定时启0x0404:启用休眠0x0400:停用用休眠  读：0001定时停在工作；0002定时启在工作，0004休眠在工作
    totalTimeHour :   "0025" , //总运行时间时
    totalTimeMin :    "0026" , //总运行时间分
}

// var testData = [
//   "0000R0dac",
//   "0001R07f1",
//   "0002R000c",
//   "0003R0001",
//   "0004R00aa",
//   "0005Rffec",
//   "0006R0032",
//   "0007R0064",
//   "0008R0dac",
//   "0009R0dac",
//   "000AR092E",
//   "0009R08fc",
//   "000BR0dac",
//   "000BR0dad",
//   "000CR0998",
//   "000CR0960",
//   "000DR0dad",
//   "000DR0960",
//   "000ER0960",
//   "000ER0961",
//   "000FR0005",
//   "000FR0060",
//   "0010R000a",
//   "0010R00a0",
//   "0011R0960",
//   "0011R00aa",
//   "0012R00aa",
//   "0012R00ab",
//   "0013R000a",
//   "0013R00ab",
//   "0014R000a",
//   "0014R00ab",
//   "0015R000a",
//   "0015R00ab",
//   "0016R000a",
//   "0016R00ab",
//   "0017R000a",
//   "0017R00ab",
//   "0018RV300",
//   "0002R0000",
//   "0002R000c",
//   "0002R000c",
// ]
////test
// for(var i = 0 ; i < testData.length; i++){
//   console.log(getCommandByCode(testData[i]))
// }

// 所有指令数据的缓存，全局且唯一的
var recDataStruct = { //第一个数值，第二个表示是否刷新
  "0000" : [null, false], //发动机速度
  "0001" : [null, false], //控制器输出电流
  "0002" : [null, false], //发动机工作状态
  "0003" : [null, false], //发动机故障状态
  "0004" : [null, false], //发动机温度
  "0005" : [null, false], //控制器温度
  "0006" : [null, false], //邮箱油位
  "0007" : [null, false], //时间（启动累计时）
  "0008" : [null, false], //时间（启动累计分）
  "0009" : [null, false], //控制器输出电压
  "000A" : [null, false], //控制器输出电压控制
  "000B" : [null, false], //充电电流
  "000C" : [null, false], //自动启动电压
  "000D" : [null, false], //自动停机电流
  "000E" : [null, false], //自动停机电压
  "000F" : [null, false], //时间（时）
  "0010" : [null, false], //时间（分）
  "0011" : [null, false], //电流低或电压高停机时间（秒）
  "0012" : [null, false], //比列调节
  "0013" : [null, false], //积分调节
  "0014" : [null, false], //微分调节
  "0015" : [null, false], //电压校正
  "0016" : [null, false], //电流校正
  "0017" : [null, false], //采样时间
  "0018" : [null, false], //读取软件版本号
  "0019" : [null, false], //产品型号
  "001A" : [null, false], //模式控制
  "001E" : [null, false], //启动时间 时
  "001F" : [null, false], //启动时间 分
  "0020" : [null, false], //加浓控制
  "0021" : [null, false], //稳定性调节
  "0022" : [null, false], //休眠时
  "0023" : [null, false], //休眠分
  "0024" : [null, false], //时间启动停止位
  "0025" : [null, false], //总运行时间时
  "0026" : [null, false], //总运行时间分
}

/**
 * 
 * @param {根据指令名字获取对应的值} name 
 */
function getRecDataValueByName(name){
  return recDataStruct[mcuCommandData[name]][0]
}

/**
 * 手动设置一遍为true，有些界面切换的时候可以立即刷新不用等指令变换
 */
function resetRecDataState(){
  Object.values(recDataStruct).forEach(element => {
    // console.log(element[1])
    element[1] = true
    // console.log(element[1])
  });
}

// var i = 0;
// Object.values(mcuCommandData).forEach(e => {
//   //console.log(e, array[i])
//   i++
// });

//计算校验和
function calcu(code) {
  let sum = 0;
  for (let i = 0; i < code.length; i++) {
    const char = code[i];
    const hex = char.charCodeAt(0).toString(16); // 将字符转换为十六进制数
    const num = parseInt(hex, 16); // 将十六进制字符串转换为数字
    sum += num; // 将数字加入总和
  }
  sum = sum << 16 >> 16
  let hexSum = sum.toString(16); //校验和
  hexSum = hexSum.padStart(4, '0')
  // console.log(hexSum); // 输出 '97e'
  return hexSum.toUpperCase();
}

//拼装指令
function getCommandByCode(code){
  let hexSum = calcu(code)
  return "##" + code + "&" + hexSum  + "**" //"01d2"
}
/**
 * 获取指令
 * @param {*} name 
 */
function getCommandByName(name){
  // console.log("----->getCommandByName()", name, mcuCommandData[name])
  if(name == "switchAuto" || name == "start" || name == "stop" || name == "update" ) {
    return getCommandByCode(mcuCommandData[name])
  }
  return getCommandByCode(mcuCommandData[name] + "R0000")
}

//检查指令是否正确
function checkCode(commandCode){
  let res = commandCode[0] == "#" && 
            commandCode[1] == "#" && 
            commandCode[11] == "&" &&
            commandCode[16] == "*" &&
            commandCode[17] == "*"
  //检查校验和
  if(res == true){
    let strCode = commandCode.substring(2, 11)
    let strCheckCode = commandCode.substring(12, 16)

    res = (calcu(strCode) == strCheckCode.toUpperCase())
  }
  return res
}

//解析发送机故障码
function EngineFaultFode(commandCode){
  var desc = "未定义";
  const num = parseInt(commandCode, 16);
  switch(num){
    case 0: desc = "正常"; break;
    case 1: desc = "电瓶电压低"; break;
    case 2: desc = "电瓶电压高"; break;
    case 3: desc = "发动机温度高"; break;
    case 4: desc = "控制器温度高"; break;
    case 5: desc = "输出电流高"; break;
    case 6: desc = "发动机启动5次未启动"; break;
    case 7: desc = "发动机启动力矩保护"; break;
    case 8: desc = "发动启动相序故障"; break;
    case 9: desc = "发动启动电压低"; break;
    case 10: desc = "发动运行超速"; break;
    case 11: desc = "发动运行速度低"; break;
    // case 12: desc = ""; break;
    case 13: desc = "控制器输出短路"; break;
    case 14: desc = "发动机停止失败"; break;
    default: desc = "未定义：" + commandCode; break;
  }

  return desc
}

//解析指令， 从返回的指令中获取值 ##0001R07f1&xxxx**
function getReceiveValue(commandCode){
  if(checkCode(commandCode) == false){
    console.error("接收的指令错误", commandCode)
    return null
  }
  let strValue = ""
  var key = commandCode.substring(2, 6)
  key = key.toUpperCase() //大小写不敏感
  switch(key){
     //整形数据
    case "0000": //发动机速度
    case "0002": //发动机工作状态
    case "0006": //邮箱油位
    case "0007": //时间（启动累计时）
    case "0008": //时间（启动累计分）
    case "000F": //时间（时）
    case "0010": //时间（分）
    case "0011": //电流低或电压高停机时间（秒）
    case "0012": //比列调节
    case "0013": //积分调节
    case "0014": //微分调节
    case "0015": //电压校正
    case "0016": //电流校正
    case "0017": //采样时间
    case "001A": //模式控制
    case "001E": //启动时间 时
    case "001F": //启动时间 分
    case "0020": //加浓控制
    case "0021": //稳定性调节
    case "0022": //休眠时
    case "0023": //休眠分
    case "0024": //时间启动停止位
    case "0025": //总运行时间时
    case "0026": //总运行时间分
      strValue = commandCode.substring(7, 11);
      recDataStruct[key] = [parseInt(strValue, 16) , true];
      return recDataStruct[key]
    //浮点型数据
    case "0001": //控制器输出电流
    case "0009": //控制器输出电压
    case "000A": //控制器输出电压控制
    case "000B": //充电电流
    case "000C": //自动启动电压
    case "000D": //自动停机电流
    case "000E": //自动停机电压
      strValue = commandCode.substring(7, 11); 
      var value = parseInt(strValue, 16) * 0.01
      value = Number(value).toFixed(2)
      recDataStruct[key] = [value , true];
      return recDataStruct[key]
    // 字符串
    case "0018": //读取软件版本号
    case "0019": //读取软件版本号
      strValue = commandCode.substring(7, 11);
      recDataStruct[key] = [strValue , true];
      return recDataStruct[key]
    case "0003": //发动机故障状态：
      strValue = commandCode.substring(7, 11);
      recDataStruct[key] = [strValue , true];
      return EngineFaultFode(strValue)
    //负数
    case "0004": // 发动机温度
    case "0005": // 控制器温度
      strValue = commandCode.substring(7, 11);
      var value = parseInt(strValue, 16)
      if(value & 0x8000){ // 负数
        value = value - 65536
      }
      recDataStruct[key] = [value , true];
      return recDataStruct[key]
    case "001C":
    case "001D":
      break
  }
  
  return null
}

function getWriteCommand(code, value){
  var str = ""
  switch(code){
    //整形
    case "000F": //时间（时）
    case "0010": //时间（分）
    case "0011": //电流低或电压高停机时间（秒）
    case "0012": //比列调节
    case "0013": //积分调节
    case "0014": //微分调节
    case "0015": //电压校正
    case "0016": //电流校正
    case "0017": //采样时间
    case "001A": //模式控制
    case "001E": //启 时
    case "001F": //启 分
    case "0020": //加浓调节
    case "0021": //稳定性调节
    case "0022": //休眠 时
    case "0023": //休眠 分
      value = Math.floor(value)
      str = value.toString(16)
      break;
    //浮点型
    case "000A": //控制器输出电压
    case "000B": //充电电流
    case "000C": //自动启动电压
    case "000D": //自动停机电流
    case "000E": //自动停机电压
      value *= 100
      value = Math.floor(value)
      str = value.toString(16)
      break
    //字符
    case "0024": //时间启动停止位
      str = value
      break
  }

  var lastFourChars = str.slice(-4).padStart(4, "0");
  code = code + "W" + lastFourChars
  // console.log(code)
  //计算校验和
  var checkCode = calcu(code)
  return "##" + code + "&" + checkCode + "**"
}

function saveSendMessageText(comamndName = 'NULL', content = 'NULL'){
  wx.request({
        url: 'https://cqygdqkj.top' + '/api/v1/zqwb/instruct_info/',
    method : 'POST',
    data:{
      instruction_name : 'send: ' + comamndName,
      response_data : content
    }
  })
}

function saveRecMessageText(comamndName = 'NULL', content = 'NULL'){
  wx.request({
        url: 'https://cqygdqkj.top' + '/api/v1/zqwb/instruct_info/',
    method : 'POST',
    data:{
      instruction_name : 'receive: ' + comamndName,
      response_data : content
    }
  })
}

function ab2Str(arrayBuffer){
  let unit8Arr = new Uint8Array(arrayBuffer);
  let encodedString = String.fromCharCode.apply(null, unit8Arr);
  return encodedString
}
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return (bit.toString(16)).padStart(2, '0')
    }
  )
  return (hexArr.join('')).toUpperCase();
}

// ******在线更新功能相关代码指令 ********

function calculateCRC16(data) {
  let crc = 0xFFFF;

  for (let i = 0; i < data.length; i++) {
    crc ^= (data.charCodeAt(i) & 0xFF) << 8;

    for (let j = 0; j < 8; j++) {
      if ((crc & 0x8000) !== 0) {
        crc = (crc << 1) ^ 0x1021;
      } else {
        crc <<= 1;
      }
    }
  }
  crc = crc & 0xFFFF
  return crc.toString(16).toUpperCase().padStart(4,'0');
}

function calculateUpdateData(count, data, length){
  var code;
  const text = ab2hex(data).padEnd(2*length, "F"); // 将 ArrayBuffer 转换为字符串

  var tmp = count.toString().padStart(4, '0') + text
  // var checkCode = calcu(tmp)
  var checkCode =  calculateCRC16(tmp);
  code = "##" + tmp + "&" + checkCode + "**"
  return code
}

//##V10030256&1234**
function beginUpdateCommand(vesion, num, len) {
  var numStr = num.toString(16).padStart(3, '0')
  var lenStr = len.toString(16).padStart(2, '0')

  var tmp = vesion + numStr + lenStr
  var checkCode = calcu(tmp)

  return "##" + tmp + "&" + checkCode + "**"
}

// 获取版本号
function getMachineVersion(){
  return recDataStruct["0018"][0]
}
// 获取失败码
function getFaultCode(){
  return recDataStruct["0003"][0]
}
// 获取失败码对应的解析信息
function getFaultCodeDesc(){
  if(recDataStruct["0003"][0] == null){
    return "未获取到信息"
  }

  return EngineFaultFode(recDataStruct["0003"][0])
}
// 获取状态码
function getStatusCode(){
  return recDataStruct["0002"][0]
}
// 获取状态码解析信息
function getStatusCodeDesc(){
  if(recDataStruct["0002"][0] == null){
    return "未获取到信息"
  }
  var res = ""
  const machineState = recDataStruct["0002"][0]
  var state = parseInt(machineState, 16)
  console.log(machineState, state)
  if ((state & 0x0001) !== 0) { //发动机停用
    console.log("停用")

    res += "停用, "
  }
  if ((state & 0x0002) !== 0) { //发动机手动
    console.log("手动")
    res += "手动, "
  }
  if ((state & 0x0004) !== 0) { //发动机自动
    console.log("自动")
    res += "自动, "
  }
  if ((state & 0x0008) !== 0) { //发动机正在运行
    console.log("正在运行")
    res += "正在运行, "
  }
  return res
}
//面板开关状态
function getHomeFaceStatus(){
  const state = recDataStruct["0002"][0]
  if ((state & 0x0001) !== 0) { //发动机停用
    return "停用"
  }
  if ((state & 0x0002) !== 0) { //发动机手动
    return "手动"
  }
  if ((state & 0x0004) !== 0) { //发动机自动
    return "自动"
  }

  return "未定义"
}
//发动机运行状态
function getMachineStatus(){
  const state = recDataStruct["0002"][0]
  if ((state & 0x0008) !== 0 
    || (state & 0x0010) !== 0 
    || (state & 0x0020) !== 0 
    ) {
    return true
  }    
  return false
}

module.exports = {
  getRecDataValueByName: getRecDataValueByName,
  resetRecDataState: resetRecDataState,
  getCommandByName: getCommandByName,
  saveSendMessageText: saveSendMessageText,
  saveRecMessageText: saveRecMessageText,
  
  checkCode : checkCode,
  getReceiveValue : getReceiveValue,
  recDataStruct : recDataStruct,
  getWriteCommand : getWriteCommand,

  getMachineVersion: getMachineVersion,

  // 状态码相关
  EngineFaultFode : EngineFaultFode,
  getFaultCode: getFaultCode,
  getFaultCodeDesc: getFaultCodeDesc,
  getStatusCode: getStatusCode,
  getStatusCodeDesc: getStatusCodeDesc,
  getHomeFaceStatus: getHomeFaceStatus, //面板开关状态
  getMachineStatus: getMachineStatus, //发动机运行状态
  // 在线更新固件功能相关
  beginUpdateCommand : beginUpdateCommand, //##V10030256&1234**
  calculateUpdateData: calculateUpdateData, //组合更新数据包
}